'use client';

import { useState, useEffect, useCallback, useRef } from 'react';
import { fetchWithErrorHandling } from '@/lib/api';
import { QueryCache } from '@/lib/query-cache';
import { notifications } from '@/components/ui/notification-toast';

// 全局查询缓存实例
const globalQueryCache = new QueryCache();

// 请求状态类型
export type RequestStatus = 'idle' | 'loading' | 'success' | 'error';

// API钩子选项
export interface UseApiOptions<T> {
  // 初始数据
  initialData?: T;
  // 是否自动获取数据
  autoFetch?: boolean;
  // 是否使用缓存
  useCache?: boolean;
  // 缓存键，默认为URL
  cacheKey?: string;
  // 缓存过期时间（毫秒）
  cacheTtl?: number;
  // 是否在组件挂载时获取数据
  fetchOnMount?: boolean;
  // 是否在窗口获取焦点时重新获取数据
  refetchOnWindowFocus?: boolean;
  // 是否在网络重新连接时重新获取数据
  refetchOnReconnect?: boolean;
  // 请求超时时间（毫秒）
  timeout?: number;
  // 最大重试次数
  maxRetries?: number;
  // 重试延迟（毫秒）
  retryDelay?: number;
  // 是否在错误时显示通知
  showErrorNotification?: boolean;
  // 错误通知标题
  errorNotificationTitle?: string;
  // 是否在成功时显示通知
  showSuccessNotification?: boolean;
  // 成功通知标题
  successNotificationTitle?: string;
  // 成功通知消息
  successNotificationMessage?: string;
  // 依赖项数组，当这些值变化时重新获取数据
  deps?: any[];
  // 请求头
  headers?: HeadersInit;
  // 请求选项
  requestOptions?: RequestInit;
  // 请求拦截器
  requestInterceptor?: (url: string, options: RequestInit) => [string, RequestInit];
  // 响应拦截器
  responseInterceptor?: (response: Response) => Promise<Response>;
  // 是否启用乐观更新
  optimisticUpdate?: boolean;
  // 乐观更新处理函数
  optimisticUpdateFn?: (currentData: T | undefined) => T;
  // 回滚处理函数
  rollbackFn?: (currentData: T | undefined, error: Error) => T | undefined;
}

// 乐观更新选项
export interface OptimisticUpdateOptions<T> {
  // 乐观更新处理函数
  updateFn: (currentData: T | undefined) => T;
  // 回滚处理函数
  rollbackFn?: (currentData: T | undefined, error: Error) => T | undefined;
}

// 突变选项
export interface MutationOptions<T, R> {
  // 是否使用缓存
  useCache?: boolean;
  // 缓存键，默认为URL
  cacheKey?: string;
  // 是否在错误时显示通知
  showErrorNotification?: boolean;
  // 错误通知标题
  errorNotificationTitle?: string;
  // 是否在成功时显示通知
  showSuccessNotification?: boolean;
  // 成功通知标题
  successNotificationTitle?: string;
  // 成功通知消息
  successNotificationMessage?: string;
  // 请求头
  headers?: HeadersInit;
  // 请求选项
  requestOptions?: RequestInit;
  // 请求拦截器
  requestInterceptor?: (url: string, options: RequestInit) => [string, RequestInit];
  // 响应拦截器
  responseInterceptor?: (response: Response) => Promise<Response>;
  // 是否启用乐观更新
  optimisticUpdate?: boolean;
  // 乐观更新处理函数
  optimisticUpdateFn?: (currentData: T | undefined) => T;
  // 回滚处理函数
  rollbackFn?: (currentData: T | undefined, error: Error) => T | undefined;
  // 成功回调
  onSuccess?: (data: R) => void;
  // 错误回调
  onError?: (error: Error) => void;
  // 完成回调
  onSettled?: (data?: R, error?: Error) => void;
  // 请求开始回调
  onMutate?: () => void;
}

/**
 * 数据获取钩子
 * 
 * 提供统一的数据获取接口，支持缓存、重试和错误处理
 * 
 * @example
 * ```tsx
 * const { data, isLoading, error, refetch } = useApi<User[]>('/api/users');
 * ```
 */
export function useApi<T = any>(url: string, options: UseApiOptions<T> = {}) {
  const {
    initialData,
    autoFetch = true,
    useCache = true,
    cacheKey = url,
    cacheTtl = 5 * 60 * 1000, // 默认5分钟
    fetchOnMount = true,
    refetchOnWindowFocus = false,
    refetchOnReconnect = false,
    timeout = 30000, // 默认30秒
    maxRetries = 3,
    retryDelay = 1000,
    showErrorNotification = true,
    errorNotificationTitle = '请求错误',
    showSuccessNotification = false,
    successNotificationTitle = '请求成功',
    successNotificationMessage,
    deps = [],
    headers,
    requestOptions,
    requestInterceptor,
    responseInterceptor,
    optimisticUpdate = false,
    optimisticUpdateFn,
    rollbackFn
  } = options;

  const [data, setData] = useState<T | undefined>(initialData);
  const [status, setStatus] = useState<RequestStatus>('idle');
  const [error, setError] = useState<Error | null>(null);
  const [retryCount, setRetryCount] = useState(0);
  
  const originalDataRef = useRef<T | undefined>(initialData);
  const isMountedRef = useRef(true);
  const controllerRef = useRef<AbortController | null>(null);
  const requestIdRef = useRef(0);
  
  // 获取数据
  const fetchData = useCallback(async (skipCache = false): Promise<T | undefined> => {
    // 生成唯一请求ID
    const requestId = ++requestIdRef.current;
    
    // 取消之前的请求
    if (controllerRef.current) {
      controllerRef.current.abort();
    }
    
    // 创建新的AbortController
    const controller = new AbortController();
    controllerRef.current = controller;
    
    // 设置请求状态
    setStatus('loading');
    setError(null);
    
    try {
      // 检查缓存
      if (useCache && !skipCache) {
        const cachedData = globalQueryCache.get<T>(cacheKey);
        if (cachedData) {
          if (isMountedRef.current && requestId === requestIdRef.current) {
            setData(cachedData);
            setStatus('success');
          }
          return cachedData;
        }
      }
      
      // 准备请求选项
      let fetchOptions: RequestInit = {
        ...requestOptions,
        headers: {
          'Content-Type': 'application/json',
          ...requestOptions?.headers,
          ...headers
        },
        signal: controller.signal
      };
      
      // 应用请求拦截器
      let fetchUrl = url;
      if (requestInterceptor) {
        [fetchUrl, fetchOptions] = requestInterceptor(fetchUrl, fetchOptions);
      }
      
      // 设置超时
      const timeoutId = setTimeout(() => {
        controller.abort();
      }, timeout);
      
      try {
        // 发送请求
        let response = await fetchWithErrorHandling(fetchUrl, fetchOptions);
        
        // 应用响应拦截器
        if (responseInterceptor) {
          response = await responseInterceptor(response);
        }
        
        // 解析响应
        const result = await response.json() as T;
        
        // 清除超时
        clearTimeout(timeoutId);
        
        // 更新缓存
        if (useCache) {
          globalQueryCache.set(cacheKey, result, cacheTtl);
        }
        
        // 更新状态
        if (isMountedRef.current && requestId === requestIdRef.current) {
          setData(result);
          setStatus('success');
          setRetryCount(0);
          
          // 显示成功通知
          if (showSuccessNotification) {
            notifications.success(
              successNotificationTitle,
              successNotificationMessage || '数据获取成功'
            );
          }
        }
        
        return result;
      } catch (err: any) {
        // 清除超时
        clearTimeout(timeoutId);
        
        // 如果是取消请求，不做处理
        if (err.name === 'AbortError') {
          return undefined;
        }
        
        // 重试逻辑
        if (retryCount < maxRetries) {
          setRetryCount(prev => prev + 1);
          
          // 指数退避重试
          const delay = retryDelay * Math.pow(2, retryCount);
          await new Promise(resolve => setTimeout(resolve, delay));
          
          // 递归重试
          return fetchData(skipCache);
        }
        
        // 更新错误状态
        if (isMountedRef.current && requestId === requestIdRef.current) {
          setError(err);
          setStatus('error');
          
          // 显示错误通知
          if (showErrorNotification) {
            notifications.error(
              errorNotificationTitle,
              err.message || '数据获取失败'
            );
          }
        }
        
        throw err;
      }
    } catch (err: any) {
      if (isMountedRef.current && requestId === requestIdRef.current) {
        setError(err);
        setStatus('error');
      }
      return undefined;
    } finally {
      // 清除控制器引用
      if (controllerRef.current === controller) {
        controllerRef.current = null;
      }
    }
  }, [url, useCache, cacheKey, cacheTtl, headers, requestOptions, requestInterceptor, responseInterceptor, timeout, maxRetries, retryDelay, showErrorNotification, errorNotificationTitle, showSuccessNotification, successNotificationTitle, successNotificationMessage, retryCount]);

  // 重新获取数据
  const refetch = useCallback(async () => {
    return fetchData(true);
  }, [fetchData]);

  // 使用乐观更新进行突变
  const mutate = useCallback(async <R = any>(
    mutationFn: (currentData?: T) => Promise<R>,
    options: OptimisticUpdateOptions<T> = { updateFn: (data) => data as T }
  ): Promise<R | undefined> => {
    const { updateFn, rollbackFn: optRollbackFn } = options;
    
    // 保存原始数据用于回滚
    originalDataRef.current = data;
    
    // 应用乐观更新
    if (updateFn) {
      setData(updateFn(data));
    }
    
    try {
      // 执行突变
      const result = await mutationFn(data);
      
      // 更新缓存
      if (useCache) {
        globalQueryCache.set(cacheKey, data, cacheTtl);
      }
      
      return result;
    } catch (err: any) {
      // 回滚数据
      const rollbackData = optRollbackFn 
        ? optRollbackFn(originalDataRef.current, err) 
        : originalDataRef.current;
      
      setData(rollbackData);
      setError(err);
      
      // 显示错误通知
      if (showErrorNotification) {
        notifications.error(
          errorNotificationTitle,
          err.message || '操作失败'
        );
      }
      
      throw err;
    }
  }, [data, useCache, cacheKey, cacheTtl, showErrorNotification, errorNotificationTitle]);

  // 发送突变请求
  const sendMutation = useCallback(async <R = any>(
    method: string,
    mutationUrl: string = url,
    body?: any,
    options: MutationOptions<T, R> = {}
  ): Promise<R | undefined> => {
    const {
      useCache: mutUseCache = useCache,
      cacheKey: mutCacheKey = cacheKey,
      showErrorNotification: mutShowErrorNotification = showErrorNotification,
      errorNotificationTitle: mutErrorNotificationTitle = errorNotificationTitle,
      showSuccessNotification: mutShowSuccessNotification = showSuccessNotification,
      successNotificationTitle: mutSuccessNotificationTitle = successNotificationTitle,
      successNotificationMessage: mutSuccessNotificationMessage = '操作成功',
      headers: mutHeaders,
      requestOptions: mutRequestOptions,
      requestInterceptor: mutRequestInterceptor,
      responseInterceptor: mutResponseInterceptor,
      optimisticUpdate: mutOptimisticUpdate = optimisticUpdate,
      optimisticUpdateFn: mutOptimisticUpdateFn = optimisticUpdateFn,
      rollbackFn: mutRollbackFn = rollbackFn,
      onSuccess,
      onError,
      onSettled,
      onMutate
    } = options;
    
    // 调用突变开始回调
    if (onMutate) {
      onMutate();
    }
    
    // 保存原始数据用于回滚
    originalDataRef.current = data;
    
    // 应用乐观更新
    if (mutOptimisticUpdate && mutOptimisticUpdateFn) {
      setData(mutOptimisticUpdateFn(data));
    }
    
    setStatus('loading');
    setError(null);
    
    try {
      // 准备请求选项
      let fetchOptions: RequestInit = {
        method,
        ...mutRequestOptions,
        ...requestOptions,
        headers: {
          'Content-Type': 'application/json',
          ...requestOptions?.headers,
          ...headers,
          ...mutRequestOptions?.headers,
          ...mutHeaders
        }
      };
      
      // 添加请求体
      if (body !== undefined) {
        fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
      }
      
      // 应用请求拦截器
      let fetchUrl = mutationUrl;
      if (mutRequestInterceptor) {
        [fetchUrl, fetchOptions] = mutRequestInterceptor(fetchUrl, fetchOptions);
      } else if (requestInterceptor) {
        [fetchUrl, fetchOptions] = requestInterceptor(fetchUrl, fetchOptions);
      }
      
      // 发送请求
      let response = await fetchWithErrorHandling(fetchUrl, fetchOptions);
      
      // 应用响应拦截器
      if (mutResponseInterceptor) {
        response = await mutResponseInterceptor(response);
      } else if (responseInterceptor) {
        response = await responseInterceptor(response);
      }
      
      // 解析响应
      const result = await response.json() as R;
      
      // 更新状态
      setStatus('success');
      
      // 显示成功通知
      if (mutShowSuccessNotification) {
        notifications.success(
          mutSuccessNotificationTitle,
          mutSuccessNotificationMessage
        );
      }
      
      // 调用成功回调
      if (onSuccess) {
        onSuccess(result);
      }
      
      // 调用完成回调
      if (onSettled) {
        onSettled(result);
      }
      
      // 如果是修改操作，刷新数据
      if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method.toUpperCase())) {
        refetch();
      }
      
      return result;
    } catch (err: any) {
      // 回滚数据
      if (mutOptimisticUpdate) {
        const rollbackData = mutRollbackFn 
          ? mutRollbackFn(originalDataRef.current, err) 
          : originalDataRef.current;
        
        setData(rollbackData);
      }
      
      // 更新错误状态
      setError(err);
      setStatus('error');
      
      // 显示错误通知
      if (mutShowErrorNotification) {
        notifications.error(
          mutErrorNotificationTitle,
          err.message || '操作失败'
        );
      }
      
      // 调用错误回调
      if (onError) {
        onError(err);
      }
      
      // 调用完成回调
      if (onSettled) {
        onSettled(undefined, err);
      }
      
      throw err;
    }
  }, [url, refetch, data, useCache, cacheKey, optimisticUpdate, optimisticUpdateFn, rollbackFn, showErrorNotification, errorNotificationTitle, showSuccessNotification, successNotificationTitle, headers, requestOptions, requestInterceptor, responseInterceptor]);

  // 创建常用的HTTP方法
  const get = useCallback(async <R = any>(
    getUrl: string = url,
    options?: MutationOptions<T, R>
  ): Promise<R | undefined> => {
    return sendMutation<R>('GET', getUrl, undefined, options);
  }, [url, sendMutation]);

  const post = useCallback(async <R = any>(
    body?: any,
    postUrl: string = url,
    options?: MutationOptions<T, R>
  ): Promise<R | undefined> => {
    return sendMutation<R>('POST', postUrl, body, options);
  }, [url, sendMutation]);

  const put = useCallback(async <R = any>(
    body?: any,
    putUrl: string = url,
    options?: MutationOptions<T, R>
  ): Promise<R | undefined> => {
    return sendMutation<R>('PUT', putUrl, body, options);
  }, [url, sendMutation]);

  const patch = useCallback(async <R = any>(
    body?: any,
    patchUrl: string = url,
    options?: MutationOptions<T, R>
  ): Promise<R | undefined> => {
    return sendMutation<R>('PATCH', patchUrl, body, options);
  }, [url, sendMutation]);

  const del = useCallback(async <R = any>(
    delUrl: string = url,
    options?: MutationOptions<T, R>
  ): Promise<R | undefined> => {
    return sendMutation<R>('DELETE', delUrl, undefined, options);
  }, [url, sendMutation]);

  // 取消请求
  const cancel = useCallback(() => {
    if (controllerRef.current) {
      controllerRef.current.abort();
      controllerRef.current = null;
    }
  }, []);

  // 清除缓存
  const invalidateCache = useCallback(() => {
    globalQueryCache.delete(cacheKey);
  }, [cacheKey]);

  // 在组件挂载时获取数据
  useEffect(() => {
    isMountedRef.current = true;
    
    if (fetchOnMount && autoFetch) {
      fetchData();
    }
    
    return () => {
      isMountedRef.current = false;
      
      // 取消未完成的请求
      if (controllerRef.current) {
        controllerRef.current.abort();
        controllerRef.current = null;
      }
    };
  }, [fetchOnMount, autoFetch, fetchData]);

  // 当依赖项变化时重新获取数据
  useEffect(() => {
    if (autoFetch && deps.length > 0) {
      fetchData();
    }
  }, [...deps, fetchData]);

  // 在窗口获取焦点时重新获取数据
  useEffect(() => {
    if (!refetchOnWindowFocus) return;
    
    const handleFocus = () => {
      if (autoFetch) {
        fetchData();
      }
    };
    
    window.addEventListener('focus', handleFocus);
    
    return () => {
      window.removeEventListener('focus', handleFocus);
    };
  }, [refetchOnWindowFocus, autoFetch, fetchData]);

  // 在网络重新连接时重新获取数据
  useEffect(() => {
    if (!refetchOnReconnect) return;
    
    const handleOnline = () => {
      if (autoFetch) {
        fetchData();
      }
    };
    
    window.addEventListener('online', handleOnline);
    
    return () => {
      window.removeEventListener('online', handleOnline);
    };
  }, [refetchOnReconnect, autoFetch, fetchData]);

  return {
    data,
    setData,
    status,
    isLoading: status === 'loading',
    isSuccess: status === 'success',
    isError: status === 'error',
    error,
    refetch,
    mutate,
    get,
    post,
    put,
    patch,
    delete: del,
    cancel,
    invalidateCache
  };
} 